//
//  ViewController.m
//  RunTimeTest
//
//  Created by YaoZhaofeng on 16/6/8.
//  Copyright © 2016年 YaoZhaofeng. All rights reserved.
//

#import "ViewController.h"
#import "CategoryObject.h"
#import "CategoryObject+CategoryTest.h"
#import "XYMessageTest.h"
#import "XYPerson.h"
#import "XYTest.h"
#import "XYViewController.h"
#import "CategoryObject+Category2.h"
#import "NSObject+FunTest.h"
#import "XYSubObject.h"

@interface Sark: NSObject
@property (nonatomic, copy) NSString *name;
- (void)speak;
@end

@implementation Sark

- (void)speak {
    NSLog(@"my name is %@", self.name);
}

@end


@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
//    XYObject *person = [[XYObject alloc] init];
    XYSubObject *man = [[XYSubObject alloc] init];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
}

- (void)whatIsThis {
    // 增加一个局部的 sark 对象
    //    id cls1 = [Sark class];
    id cls = [Sark class];
    void *obj = &cls;
    [(__bridge id)obj speak];
}

- (IBAction)btnClick:(id)sender {
    NSInteger tag = ((UIButton*)sender).tag;
    switch (tag) {
        case 100:
        {
            //类别测试
            [self testCategory];
        }
            break;
        case 101:
        {
            //self&super
            [self differenceBetweenSelfWithSuper];
        }
            break;
        case 102:
        {
            //动态方法解析
            [self testDynamicMethod];
            
        }
            break;
        case 103:
        {
            //消息重定向
            [self testMessageForwardTarget];
            
        }
            break;
        case 104:
        {
            //getIMPLFromSelector
            XYTest *test2 = [[XYTest alloc] init];
        }
            break;
        case 105:
        {
            //消息转发成功
            [self testMessageForwardInvocationSucess];
        }
            break;
        case 106:
        {
            //消息转发失败
            [self testMessageForwardInvocationFail];
        }
            break;
        case 107:
        {
            //消息转发失败
            [self testNSNull];
        }
            break;
        case 108:
        {
            //发消息效率
            [self testFunctionInvoke];
        }
            break;
        case 109:
        {
            //动态添加类方法
            [self dynamicAddClassMethod];
        }
            break;
        case 110:
        {
            //测试类和元类的关系
            [self testClassRelation];
        }
            break;
        default:
            break;
    }
}

- (void)propertyTest{
    XYPerson *person = [[XYPerson alloc] init];
//    NSLog(@"dic::%@",[person allProperties]);
    NSLog(@"%@",person);
}


/**
 *  self指的是当前方法的调用者，即当前类
 *  super并不是指父类，它是一个编译器的指令符号，告诉编译器在编译的时候调用谁的方法
 *  所以，不管是对self还是super发送消息，消息主体都是self，只是查找方法位置有区别
 * [self class]编译器最终会转换成objc_msgSend(self, @selector(class)), 一路查找class方法，最终找到顶级父类NSObject类，并调用objc_getClass(self);
 [super class]相当于
 struct objc_super1 {
 __unsafe_unretained id receiver;
 Class superClass;
 };
 struct objc_super1 obj_super = {self,class_getSuperclass(object_getClass(self))};
 objc_msgSendSuper(&obj_super,@selector(class));
 
 其中，消息主体receiver依然是self
 */
- (void)differenceBetweenSelfWithSuper {
    NSLog(@"[self class is] %@",NSStringFromClass([self class]));
    NSLog(@"[super class] is %@",NSStringFromClass([super class]));
    NSLog(@"[self superclass] is %@",NSStringFromClass([self superclass]));
}

- (void)categoryFun {
    NSLog(@"这是我动态添加的元类方法");
}

/**
 *动态添加类方法
 *
 *调用一个类的类方法，去它的元类中查找实例方法，如果没有再去元类的父类中查找
 *
 *如果调用NSObject的类方法，先去它的元类中查找，如果没有再去NSObject的元类的父类中查找，
    而NSObject的元类的父类正好是NSObject本身，所以如果NSObject分别声明了同名的类方法和实例方法，
    而只有实例方法有实现，那么调用类方法的时候就会调用实例方法的实现。
 */
- (void)dynamicAddClassMethod {
    Class metaClass = objc_getMetaClass("CategoryObject");
    class_addMethod(metaClass, @selector(categoryFun), method_getImplementation(class_getInstanceMethod([self class], @selector(categoryFun))), "v@:");
    CategoryObject *testObject = [[CategoryObject alloc] init];
    [testObject categoryFun];
    [CategoryObject categoryFun];
}

/**
 *  在category中添加属性
 */
- (void)testCategory{
    
    CategoryObject *testObject = [[CategoryObject alloc] init];
//    testObject.categoryProperty =nil;// @"just for test";
    [testObject doSomething];
    
    NSLog(@"testObject.categoryProperty is %@",testObject.categoryProperty);
    unsigned int i, count = 0;
    objc_property_t * properties = class_copyPropertyList(NSClassFromString(@"CategoryObject"), &count );
    if ( count == 0 )
    {
        NSLog(@"没有属性");
        free( properties );
        return;
    }
    
    NSMutableArray * list = [NSMutableArray array];
    
    for ( i = 0; i < count; i++ ) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
        NSLog(@"propertyName::%@", propertyName);
    }
    free(properties);
}

/**
 *  动态方法解析测试，动态的给类添加方法实现
 */
- (void)testDynamicMethod{
    XYMessageTest *test = [[XYMessageTest alloc] init];
    if ([test respondsToSelector:@selector(myDynamicMethod)]) {
        NSLog(@"动态方法解析：respondsToSelector::YES");
    } else {
        NSLog(@"动态方法解析：respondsToSelector::NO");
    }
    [test performSelector:@selector(myDynamicMethod)];
}

- (void)testMessageForwardTarget {
    XYMessageTest *test = [[XYMessageTest alloc] init];
    [test performSelector:@selector(doSomething)];
}

- (void)testMessageForwardInvocationSucess {
    XYMessageTest *test = [[XYMessageTest alloc] init];
    [test performSelector:@selector(foo)];
}

- (void)testMessageForwardInvocationFail {
    XYMessageTest *test = [[XYMessageTest alloc] init];
    [test performSelector:@selector(unrecognizedMethod)];
}




- (void)function:(int)i{
    int j = 100;
    while (j > 0) {
        j--;
    }
}

/**
 *  测试发送消息和直接根据方法地址并调用方法的效率
 *结论：次数比较多的时候，直接根据方法地址调用方法比发送消息效率要高
 *1000次反而是前者更快、？
 */
- (void)testFunctionInvoke{
    int count = 1000;
    NSTimeInterval interval1 = [[NSDate date] timeIntervalSince1970];
    NSLog(@"start::%f",interval1);
    for (int i = 0; i< count; i++) {
        [self function:i];
    }
    NSTimeInterval interval2 = [[NSDate date] timeIntervalSince1970];
    NSLog(@"end::%f",interval2);
    NSLog(@"发消息cost::%f",interval2-interval1);
    
    void(*function)(id,SEL,int);
    function = (void(*)(id,SEL,int))[self methodForSelector:@selector(function:)];
    
    NSTimeInterval interval3 = [[NSDate date] timeIntervalSince1970];
    NSLog(@"start::%f",interval3);
    for (int i = 0; i< count; i++) {
        function(self,@selector(function:),i);
    }
    NSTimeInterval interval4 = [[NSDate date] timeIntervalSince1970];
    NSLog(@"end::%f",interval4);
    NSLog(@"直接调用方法cost::%f",interval4-interval3);
}

/**
 *  测试NSNull的类别功能
 */
- (void)testNSNull{
    NSString *nullObject = [NSNull null];
    
    NSUInteger length = [nullObject length];
    NSLog(@"length is %lu",(unsigned long)length);
    NSLog(@"function::%@",NSStringFromSelector(_cmd));
}

- (void)testClassRelation {
    BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
    BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
    BOOL res3 = [(id)[XYPerson class] isKindOfClass:[XYPerson class]];
    BOOL res4 = [(id)[XYPerson class] isMemberOfClass:[XYPerson class]];
    NSLog(@"res1::%i res2::%i res3::%i res4::%i", res1, res2, res3, res4);
}

@end
